

import vue, { h } from 'vue'
import CryptoJS from 'crypto-js'
import dayjs from "dayjs";
import GModel from './g-model.vue';
import SetAnimation from "./set-animation.vue";
import ChangePassword from './change-password.vue';
import JsAdd from './add.vue';
import jstable from './table.vue';
import CheckExcelItem from './check-excel-item.vue';
import setRolePower from './role-set-power.vue';

/**
 * 所有参数参考ELEMENT UI API 文档
 * @param {url:'模态窗口路径',attrs:'模态窗口属性',on:'模态窗口事件',scopedSlots:'模态窗口插槽'} options 
 * @returns  vue 实例
 */
export function openModel(options = { url: "", attrs: {}, on: {}, scopedSlots: {} }) {
    let { url, attrs, on, scopedSlots } = options;
    let ele = document.createElement('div');
    return new vue({
        components: { GModel },
        render: function (h) {
            let defaultAttrs = {
                title: '消息',
                width: "50%",
                'append-to-body': true,
                "close-on-click-modal": false,
                "close-on-press-escape": true
            };
            let evs = {
                uclose: (val) => {
                    this.$destroy();
                }
            };
            let p = Object.assign(
                { props: { url } },
                { attrs: Object.assign(defaultAttrs, attrs) },
                { on: Object.assign(evs, on) },
                { scopedSlots: scopedSlots }
            );
            // return (<g-model {...p}></g-model>)
            return h(GModel, p)
        },

    }).$mount(ele);
}

/**
 * 
 * @param { ui 设置动画} isshow 传 true 显示 false 隐藏
 * @returns 
 */
export function setAnimation(isshow) {
    let ele = document.createElement('div');
    return new vue({
        components: { SetAnimation },
        render: (h) => h(SetAnimation, { attrs: { isshow: isshow } })
    }).$mount(ele);
}

/**
 * 
 * @returns ui 修改密码
 */
export function changePassword(col) {
    let ele = document.createElement('div');
    return new vue({
        components: { ChangePassword },
        render: (h) => h(ChangePassword, col)
    }).$mount(ele);
}


/**
 * 
 * @param {excel表头信息 label:value 对象格式} items 
 * @param {处理生成excel 方法} callback 
 * @param {弹窗属性} modelAttrs 
 * @param {生成excel按钮文字} commitText 
 */
export function openDownloadExcel(items, callback = () => { }, modelAttrs = {}, commitText = "生成EXCEL",) {
    let vm = openModel({
        attrs: Object.assign({
            title: '选择需要下载的excel项',
            width: "568px"
        }, modelAttrs),
        scopedSlots: {
            default: () => h(CheckExcelItem, {
                attrs: { items, commitText }, on: {
                    save: (val) => {
                        callback(val)
                        vm.$destroy();
                    }
                }
            }),
        }
    })
}


/**
 * 
 * @param {MessageBox} MessageBox 
 * @param {下载路径} url 
 * @param {保存的文件名} filename 
 * @param {下载提示弹窗属性} option 
 */
export function downloadExcel(MessageBox, url, filename, option = {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
}) {
    MessageBox.confirm('你是否确定下载？', '提示', option).then(() => {
        let time = dayjs().format("YYYY-MM-DD HH时mm分ss");
        filename += '-' + time;
        getBlob(url, function (blob) {
            saveAs(blob, filename);
        });
        console.log(filename);
    }).catch(err => console.log(err));
    function getBlob(url, cb) {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", url, true);
        xhr.responseType = "blob";
        xhr.onload = function () {
            if (xhr.status === 200) {
                cb(xhr.response);
            }
        };
        xhr.send();
    }
    function saveAs(blob, filename) {
        if (window.navigator.msSaveOrOpenBlob) {
            navigator.msSaveBlob(blob, filename);
        } else {
            var link = document.createElement("a");
            var body = document.querySelector("body");
            link.href = window.URL.createObjectURL(blob);
            link.download = filename;
            // fix Firefox
            link.style.display = "none";
            body.appendChild(link);
            link.click();
            body.removeChild(link);
            window.URL.revokeObjectURL(link.href);
        }
    }
}


/**
 * 
 * @param {表单属性} attrs 
 * @param {表单容器，传入此参数，去掉模态窗} el 
 * @returns 
 */
export function createForm(attrs, el = undefined) {
    let vm = new vue({
        components: { JsAdd },
        render: (h) => {
            if (!attrs.on) {
                attrs.on = {
                    close: () => vm.$destroy()
                }
            } else {
                attrs.on = Object.assign({
                    close: () => vm.$destroy()
                }, attrs.on)
            }
            return h(JsAdd, attrs)
        }
    });
    if (el) {
        attrs.attrs.isModel = false;
        return vm.$mount(el);
    } else {
        attrs.attrs.isModel = undefined;
        let ele = document.createElement('div');
        return vm.$mount(ele);
    }
}


/**
 * 
 * @param {表格容器} el 
 * @param {表格参数} attrs 
 * @returns 
 */
export function createTable(el, attrs) {
    return new vue({
        components: { jstable },
        render: (h) => h(jstable, attrs),
    }).$mount(el);
}


/**
 * 
 * @param {角色名称} roleName 
 * @param {事件load,authMenu,authFunc,batchAuthMenus,batchAuthFuncs} events 
 * @param {是否使用测试数据} testData 
 * @param {模态窗属性} modelAttrs 
 */
export function createRolePower(roleName, events = {}, testData = false, modelAttrs = {}) {
    let defaultModelAttrs = {
        title: `【${roleName}】- 授权`, width: '1200px',
    };
    if (typeof (roleName) == "object") {
        modelAttrs = Object.assign(modelAttrs, roleName);
    }
    let ons = {
        load: (callback) => { callback(); },
        batchAuthMenus: (val, items, callback) => { callback(); },
        authMenu: (val, id) => { },
        batchAuthFuncs: (val, items, callback) => { callback(); },
        authFunc: (val, pid, id, item, callback) => { callback(); }
    };
    openModel({
        attrs: Object.assign(defaultModelAttrs, modelAttrs.attrs), on: modelAttrs.on, scopedSlots: {
            default: () => h(setRolePower, { on: Object.assign(ons, events), attrs: { testData: testData } }),
            ...modelAttrs.scopedSlots
        }
    })
}

// 十六位十六进制数作为密钥
const paw = CryptoJS.enc.Utf8.parse("GYC_KEY_CHAO1234");
// 十六位十六进制数作为密钥偏移量
const iv = CryptoJS.enc.Utf8.parse("GYC_KEY_CHAO7894");
//以下方法中 mode就是加密模式，padding是填充。

/**
 * 
 * @param {原文} word 
 * @returns 加密方法返回加密后的密文
 */
export function encrypt(word) {
    const key = CryptoJS.enc.Utf8.parse(paw);
    const srcs = CryptoJS.enc.Utf8.parse(word);
    const encrypted = CryptoJS.AES.encrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });
    return encrypted.toString();
}

/**
 * 
 * @param {密文} word 
 * @returns 解密方法返回加密前的原文
 */
export function decrypt(word) {
    const key = CryptoJS.enc.Utf8.parse(paw);
    const decrypt = CryptoJS.AES.decrypt(word, key, { iv: iv, mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });
    return CryptoJS.enc.Utf8.stringify(decrypt).toString();
}


export function hasVerticalScrollbar(element) {
    return element.scrollHeight > element.clientHeight;
}

export function hasHorizontalScrollbar(element) {
    return element.scrollWidth > element.clientWidth;
}


/**
 *
 * @param {处理目标对象} obj
 * @param {过滤属性相关方法} func
 * @returns
 */
export function objectFilter(obj, func) {
    if (typeof obj != 'object') {
        return;
    }
    let res = Object.fromEntries(Object.entries(obj).filter(a => func(a[1], a[0])));
    return res;
}

/**
 *
 * @param {求和目标数组} arr
 * @param {处理求和的字段相关逻辑} func
 * @param {保留小数位数} decimals
 * @param {去除多余零} removeZero
 * @returns number
 */
export function sum(arr, func, decimals = 0, removeZero = false) {
    if (Array.isArray(arr)) {
        if (arr.length == 0) {
            return 0;
        }
        let res = 0;
        if (func) {
            res = arr
                .map(a => func(a))
                .reduce((a, b) => a + b)
        } else {
            res = arr.reduce((a, b) => a + b)
        }
        if (decimals !== 0) {
            res = Number
                .parseFloat(res)
                .toFixed(decimals);
        }
        if (removeZero) {
            res = Number.parseFloat(res)
        }
        return res;
    } else {
        return 0;
    }
}

/**
 * 
 * @param {原始数组} arr 
 * @param {条件数组} arr1 
 * @param {过滤条件} func 
 * @returns 
 */
export function arrInArr(arr, arr1, func) {
    return arr.filter(a => arr1.includes(func(a)));
}
